package com.fishleap.sqlSession;

import com.fishleap.pojo.MapperStatement;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zlg
 * @create 2020-04-28 23:57
 * ResultSetHandler: 主要用于结果集的映射
 */
public class ResultSetHandler {

    private MapperStatement mapperStatement;

    private ResultSet resultSet;

    public ResultSetHandler(MapperStatement mapperStatement, ResultSet resultSet) {
        this.mapperStatement = mapperStatement;
        this.resultSet = resultSet;
    }

    // 封装返回的结果集并获取
    public <E> List<E> getResultSet() throws Exception{
        String resultType = mapperStatement.getResultType();
        Class<?> resultTypeClass = (resultType != null) ? Class.forName(resultType) : null;

        ArrayList<Object> objects = new ArrayList<>();
        while (resultSet.next()) {
            // 每一条记录封装一个对象
            Object o = resultTypeClass.newInstance();
            // 获取元数据
            ResultSetMetaData metaData = resultSet.getMetaData();
            // 索引从1开始,从0的话会: java.sql.SQLException: Column index out of range
            for (int i = 1; i <= metaData.getColumnCount(); i++) {
                // 字段名
                String columnName = metaData.getColumnName(i);
                // 字段值
                Object value = resultSet.getObject(columnName);

                // 根据反射或内省设置对象的属性值,如属性中没有password时会报错
                // 这里对应的javaBean里的属性需与数据库一一对应,属性不是只是一部分,不然会报下面错误
                // java.beans.IntrospectionException: Method not found: isPassword
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnName, resultTypeClass);
                Method writeMethod = propertyDescriptor.getWriteMethod();
                // 需要给字段的value参数值,不然报下面异常
                // java.lang.IllegalArgumentException: wrong number of arguments
                writeMethod.invoke(o,value);
            }
            objects.add(o);
        }

        return (List<E>) objects;
    }
}
